﻿#region jsonEagriUhul

/*
 * module for communication between apps
 * 
 * please use your own namespace, better dont use my (default) one !!
 * 
 * created by: asida@centrum.cz
 * 
 * initial implementation: 6.12.2011
 * last updated: 26.3.2012
 */

using System.IO;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Collections.Specialized;


namespace SilverlightApplication1 //give it your namespace here
{

  

  public class XapExplorerApplicationBase : UserControl
  {
    protected bool isCommInitialized;
    protected ObservableCollection<string> commands;
    protected Dictionary<string, string> environment;
    protected Dictionary<string, string> webserviceEntryPoints;
    protected string currentAppName;


    protected XapExplorerApplicationBase()
    { 
      isCommInitialized = false;

      this.SizeChanged += new SizeChangedEventHandler(XapExplorerApplicationBase_SizeChanged);
    }




    private void XapExplorerApplicationBase_SizeChanged(object sender, RoutedEventArgs e)
    {

      if (!isCommInitialized)
        if (commands == null && this.Resources.Contains("uhul_eAgri_Commands") && this.Resources.Contains("uhul_eAgri_Environment"))
        {
          commands = (ObservableCollection<string>)this.Resources["uhul_eAgri_Commands"];
          environment = (Dictionary<string, string>)this.Resources["uhul_eAgri_Environment"];
          currentAppName = (string)this.Resources["uhul_eAgri_AppName"];
          webserviceEntryPoints = (Dictionary<string, string>)this.Resources["ApplicationWebserviceEntryPoints"];
          
          isCommInitialized = true;
          onStart(); //run OnStart before hookup and send first command

          commands.CollectionChanged += new NotifyCollectionChangedEventHandler(processCommand);

          commands.Add(
            new Command()
            {
              CommandType = CommandTypeEnum.ActivateCommunication,
              CommandParameter = currentAppName
            }.ToJson()
          );

        }

    }





    private void processCommand(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
      for (int i = 0; i < e.NewItems.Count; i++)
      {
        Command c = Command.Parse((string)e.NewItems[i]);
        if (c.TargetApplicationName == currentAppName || string.IsNullOrEmpty(c.TargetApplicationName))
          if (c.CommandType == CommandTypeEnum.StopApplication)
          {
            //stop listen by remove reference to commands
            commands.CollectionChanged -= new NotifyCollectionChangedEventHandler(processCommand);
            commands = null;
            onEnd();
            return;
          }

          else if((int)c.CommandType > 255)
            onCommand(c);
        
      }
    }




    protected virtual void onCommand(Command c)
    { 
      
    }


    protected virtual void onStart()
    {

    }


    protected virtual void onEnd()
    {

    }


  }



  /// <summary>
  /// zakladni trida, ktera poskytuje funkce pro serializaci objektu do json formatu
  /// ktery se pouziva pro vymenu dat mezi objekty
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public abstract class JsonSerializable<T>
  {


    /// <summary>
    /// serializuje instanci objektu do Json
    /// </summary>
    /// <returns>vraci <c>string</c> s Json reprezentaci objektu</returns>
    public string ToJson()
    {
      using (var memoryStream = new MemoryStream())
      {
        //var serializer = new DataContractSerializer(typeof(T));
        //serializer.WriteObject(memoryStream, this);

        var serializer = new DataContractJsonSerializer(typeof(T));
        serializer.WriteObject(memoryStream, this);

        memoryStream.Seek(0, SeekOrigin.Begin);

        var reader = new StreamReader(memoryStream);
        string content = reader.ReadToEnd();
        return content;
      }
    }





    /// <summary>
    /// Staticka funkce, nacte ze vstupniho <c>string</c> data
    /// a prevede je na konkretni objekt jako je jprl, ku, apod...
    /// </summary>
    /// <param name="data">vstupni retezec s Json daty</param>
    /// <returns>objekt dle typu</returns>
    public static T Parse(string data)
    {
      using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(data)))
      {
        //var serializer = new DataContractSerializer(typeof(T));
        //T theObject = (T)serializer.ReadObject(stream);
        //return theObject;


        DataContractJsonSerializer s =
          new DataContractJsonSerializer(typeof(T));
        T theObject = (T)s.ReadObject(stream);
        return theObject;

      }
    }


  }




  /// <summary>
  /// vyjmenovane typy jprl
  /// </summary>
  public enum TypJprlEnum : int
  {
    psk = 0,
    bzl = 1,
    jp = 2,
    op = 3
  }





  /// <summary>
  /// vyjmenovane typy parcel
  /// </summary>
  public enum TypParcelyEnum : int
  {
    kn = 0,
    pk = 1
  }






  /// <summary>
  /// jednotka prostoroveho rozdeleni lesa, dle lesniho zakona
  /// </summary>
  public class Jprl : JsonSerializable<Jprl>
  {

    public TypJprlEnum TypJprl { get; set; }
    public int LhcKod { get; set; }
    public int Odd { get; set; }
    public int OddId { get; set; }
    public string Dil { get; set; }
    public string Por { get; set; }
    public int Maj { get; set; }
    public int Katuze { get; set; }
    public string PskBzlJpOp { get; set; }
    public string BzlJpOpId { get; set; }

  }





  /// <summary>
  /// lesni hospodarska osnova, majetek jednoho vlasnika
  /// </summary>
  public class Lhc : JsonSerializable<Lhc>
  {
    public int LhcKod { get; set; }
    public int Maj { get; set; }
  }






  /// <summary>
  /// describes command types for communication between apps
  /// </summary>
  public enum CommandTypeEnum : int
  {

    // XapExplorer commands reserved 0 - 255
    /// <summary>
    /// XapExplorer loads and run new app from available apps
    /// given by TargetApplicationName property in command
    /// and saves command parameter (if present)
    /// </summary>
    RunApplication = 1,

    /// <summary>
    /// XapExplorer takes existing app and creates new one based on this
    /// with new unique name supplied in command parameter. Then runs this new app
    /// </summary>
    //RunAppClone = 2,

    /// <summary>
    /// stop application given by TargetApplicationName
    /// </summary>
    StopApplication = 3,

    /// <summary>
    /// after application success load, it can tell back to XapExplorer
    /// that is ready to listen to commands.
    /// If pending commmand exists for this app XapBrowser sends it to app now
    /// </summary>
    ActivateCommunication = 4,

    /// <summary>
    /// changes text on running application tab button
    /// to text given by Command parameter
    /// </summary>
    ChangeAppTabBtnLabel = 5,

    /// <summary>
    /// increases wait counter +1 and begins wait animation
    /// </summary>
    BeginWait = 6,

    /// <summary>
    /// decreases wait counter -1 and if counter = 0 stops wait animation
    /// </summary>
    EndWait = 7,

    /// <summary>
    /// Activates running app (shows its GUI as top most)
    /// </summary>
    ActivateApp = 8,

    /// <summary>
    /// Activates running app (shows its GUI as top most)
    /// </summary>
    ActivateAppAsPrevious = 9,


    //app generic messages

    ///// <summary>
    ///// XapExplorer can send this message to any app to let it know
    ///// that this app will be killed (stopped)
    ///// </summary>
    //PrepareStopApplication = 256,

    //user defined messages...

    ZmenaLhc = 500,
    ZmenaLhcMaj = 501,
    ZmenaJprl = 502,
    ZmenaKu = 503,
    ZmenaParcely = 504,

    /// <summary>
    /// command for map to move its current view position
    /// if targetAppName is specified, only this map should move
    /// </summary>
    MapMove = 505,

    ZobrazInfoOParcele = 506,
    ZobrazInfoOJprl = 507,
    ZobrazInfoOLhc = 508,

  }




  /// <summary>
  /// trida Command, predstavuje prikaz, ktery je mozne odeslat/prijmout v aplikaci
  /// </summary>
  public class Command : JsonSerializable<Command>
  {
    public CommandTypeEnum CommandType { get; set; }
    public string TargetApplicationName { get; set; }
    public string CommandParameter { get; set; }
  }




}

#endregion jsonEagriUhul
